/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.util;

import java.beans.*;
import java.lang.reflect.*;
import ch.trackedbean.common.*;

/**
 * {@link IValueAccessor} for simple properties.
 * 
 * @param <T> The return type
 * @author M. Hautle
 */
public class PropertyAccessor<T> implements IValueAccessor<T> {
	/** The property. */
	private final PropertyDescriptor property;

	/**
	 * Default constructor.
	 * 
	 * @param type The type on which the property is located
	 * @param property The propertyname
	 */
	public PropertyAccessor(Class type, String property) {
		this.property = BeanUtils.getDescriptor(type, property);
	}

	/**
	 * Default constructor.
	 * 
	 * @param property The property
	 */
	public PropertyAccessor(PropertyDescriptor property) {
		this.property = property;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getPath() {
		return property.getName();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	@SuppressWarnings("unchecked")
	public T getValue(Object element, T fallback) {
		try {
			final Method m = property.getReadMethod();
			return m != null ? (T) m.invoke(element) : fallback;
		} catch (Exception e) {
			throw new TechnicalException("Error while reading " + property.getName() + " on " + element.getClass().getName(), e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean setValue(Object element, T value) {
		try {
			final Method m = property.getWriteMethod();
			if (m == null)
				return false;
			m.invoke(element, value);
		} catch (Exception e) {
			throw new TechnicalException("Error while writing " + property.getName() + " on " + element.getClass().getName(), e);
		}
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	@SuppressWarnings("unchecked")
	public Class<T> getType() {
		return (Class<T>) property.getPropertyType();
	}
}
